/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JPanel;

/**
 *
 * @author Misja
 */
public class GameFieldPanel extends JPanel implements KeyListener {

    private ArrayList<Field> fields;

    public GameFieldPanel() {
        this.fields = new ArrayList();
        for (int x = 0; x < 10; x++) {
            for (int y = 0; y < 10; y++) {
                this.fields.add(new Field(x, y));
            }
        }
        this.fields.get(5).setPart(new Player());
        this.fields.get(12).setPart(new Box());
        this.fields.get(13).setPart(new Box());
        this.fields.get(14).setPart(new Box());
        this.fields.get(24).setPart(new Box());

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Iterator<Field> it = this.fields.iterator();
        while (it.hasNext()) {
            Field f = it.next();
            f.draw(g);
        }
    }

    public Field findPlayerField() {
        Iterator<Field> it = this.fields.iterator();
        while (it.hasNext()) {
            Field f = it.next();
            if (f.getPart() != null && f.getPart() instanceof Player) {
                return f;
            }
        }
        return null;
    }

    public Field findNeighbourField(Field field, char direction) {

        int xCoordinate = field.getxCoordinate();
        int yCoordinate = field.getyCoordinate();

        switch (direction) {
            case 'r':
                xCoordinate = xCoordinate + 30;
                break;
            case 'l':
                xCoordinate = xCoordinate - 30;
                break;
            case 'u':
                yCoordinate = yCoordinate - 30;
                break;
            case 'd':
                yCoordinate = yCoordinate + 30;
                break;
        }

        Iterator<Field> it = this.fields.iterator();
        while (it.hasNext()) {
            Field f = it.next();
            if (f.getxCoordinate() == xCoordinate && f.getyCoordinate() == yCoordinate) {
                return f;
            }
        }
        return null;
    }
    


      
      
//     helperclass bestaat er een buur.
//      
//     bool move (loc,direction){ kan ik bewegen
//       if(f.get(p) = false){ zit er niets in > kan bewegen
//          return true;
//      }else if(f.get(p) = true && f.isCanMove = false){ zit er iets in en kan het niet bewegen > niet bewegen
//          return false;
//      }else if(f.get(p) = true && f.isCanMove = true){
//        return move(loc,direction+1);
//       }
//       return true;
    
    /* In deze methode word een speler bewogen*/
    public void movePlayer(Field firstField, char direction) {

        HashMap<Field, GamePart> changes = new HashMap<>();
        Field currentField;
         
        // buur veld wordt bepaald en opgeslagen.
        Field neighbourField = findNeighbourField(firstField, direction);

        // het spel element van het eerste veld wordt tijdelijk bewaard.
        GamePart currentPart = firstField.getPart();
        boolean endCondition = false;

        /* Hier wordt er gekeken of er wel een buur veld is
         * als er geen buur veld is dan stop de functie. */
        if (neighbourField == null) {
            return;
        }

        // Eerste actie wordt altijd opgeslagen.
        changes.put(firstField, null);

        while (endCondition == false) {
            // Hier word gekeken of er een GamePart zit in het buur veld.
            if (neighbourField.getPart() == null) {
                // Eind conditie is vervult loop stopt.
                changes.put(neighbourField, currentPart);
                endCondition = true;
                break;
            }

            // Hier word gekeken of het onder deel kan worden verplaats;
            if (neighbourField.getPart().isCanMove()) {
                // Het huidige GamePart wordt in het buur veld opgeslagen.
                changes.put(neighbourField, currentPart);
                // Huidige GamePart wordt gevuld met het op object van het buur veld.
                currentPart = neighbourField.getPart();
                // Het huidige veld wordt het buur veld.
                currentField = neighbourField;
                // Het buur veld wordt de het buur veld van het huidige veld.
                neighbourField = findNeighbourField(currentField, direction);

                // Als er geen buur veld is dan stop de loop.
                if (neighbourField == null) {
                    break;
                }

            } else {
                // Als een onderdeel niet verplaatsbaar is stop de loop.
                break;
            }
        }
        
        // Kijkt eraan de eindconditie is voldaan zoja dan voert hij het uit.
        if (endCondition) {
            Iterator<Entry<Field, GamePart>> it = changes.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Field, GamePart> entry = it.next();
                Field t = entry.getKey();
                GamePart p = entry.getValue();
                t.setPart(p);
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyPressed(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        Field f = this.findPlayerField();
        switch (e.getKeyCode()) {
            case KeyEvent.VK_UP:
                this.movePlayer(f, 'u');
                break;
            case KeyEvent.VK_DOWN:
                this.movePlayer(f, 'd');
                break;
            case KeyEvent.VK_LEFT:
                this.movePlayer(f, 'l');
                break;
            case KeyEvent.VK_RIGHT:
                this.movePlayer(f, 'r');
                break;
        }
        repaint();
    }
}
